#import "ToyWinEPS.h"
#import <appkit/TextField.h>
#import <appkit/NXImage.h>
#import <appkit/NXEPSImageRep.h>
#import <appkit/NXBitmapImageRep.h>
#import <libc.h>
#import <string.h>
#import "ToyView.h"
#import "common.h"

@implementation ToyWinEPS

/* Overload */
- makeComment:(commonInfo *)cinf
{
	sprintf(cinf->memo, "%d x %d  EPS", cinf->width, cinf->height);
	return self;
}

/*
    EPSをTIFFに変換するため、imageをいったんstreamに書き出して再度読み込み
    する。一般に用いられている Sharon Zakhour の "TIFFandEPS" の方法、即ち、
	[epsimg lockFocus];
	tiffrep = [[NXBitmapImageRep alloc] initData: NULL fromRect: &rect];
	[epsimg unlockFocus];
	[tiffrep getDataPlanes: map];
    では、meshデータのRGB値の後に余分の値が１つ付いてしまう。これはドキュ
    メントにも記述されておらず、ビットマップデータを扱う上で厄介であるため
    採用しなかった。
*/
static NXBitmapImageRep *tiffrep = nil;
static commonInfo common_info;

/* Local */
- (commonInfo *)EPStoBitmap: (unsigned char **)map
{
	commonInfo *ip;
	NXStream *stream;
	NXSize cSize;

	[[[self toyView] image] getSize: &cSize];
	if ((cSize.width >= MAXWidth)
	|| (stream = NXOpenMemory(NULL, 0, NX_READWRITE)) == NULL)
		return NULL;
	ip = &common_info;
	[[[self toyView] image] writeTIFF:stream];
    	NXFlush(stream);   
	NXSeek(stream, 0L, NX_FROMSTART);
	tiffrep = [[NXBitmapImageRep alloc] initFromStream: stream];
	NXClose(stream);

	ip->width	= [tiffrep pixelsWide];
	ip->height	= [tiffrep pixelsHigh];
	ip->xbytes	= [tiffrep bytesPerRow];
	ip->type	= Type_tiff;
	ip->bits	= [tiffrep bitsPerSample];
	ip->numcolors	= [tiffrep numColors]; /* without alpha */
	ip->alpha	= [tiffrep hasAlpha];
	ip->isplanar	= [tiffrep isPlanar];
	ip->cspace	= [tiffrep colorSpace];
	ip->palette	= NULL;
	ip->palsteps	= 0;
	ip->memo[0]	= 0;
	[tiffrep getDataPlanes: map];
	return ip;
}

/* Overload */
- freeTempBitmap
{
	if (tiffrep != nil) {
		[tiffrep free];
		tiffrep = nil;
	}
	return self;
}

/* Overload */
- (int)getBitmap:(unsigned char **)map info:(commonInfo **)infp
{
	*infp = [self EPStoBitmap: map];
	return (*infp) ? 0 : Err_MEMORY;
}

/* Overload */
- saveAsTiff: sender
{
	NXStream *stream;
	int	fd = -1;
	char	*sav;
	int	type;
	float	factor;

	sav = [super getSaveTiffname: imageFilename jpeg: NO
		compress: &type by: &factor];
	if (sav == NULL) /* canceled */
		return self;
	if ((fd = open(sav, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0
	|| (stream = NXOpenFile(fd, NX_WRITEONLY)) == NULL) {
		if (fd >= 0) (void) close(fd);
		errAlert(sav, Err_SAVE);
		return self;
	}
	/* type = none/lzw */
	[[[self toyView] image] writeTIFF:stream
		allRepresentations:NO usingCompression:type andFactor:0.0];
	NXClose(stream);
	(void)close(fd);
	return self;
}

/* Overload */
- saveAsEPS: sender
{
	NXStream *stream;
	NXEPSImageRep *rep;
	char	*sav;
	char	*eps;
	int i, n;

	sav = [self getSavename: imageFilename with:Type_eps];
	if (sav == NULL) /* canceled */
		return self;
	stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	if (stream == NULL) {
		errAlert(sav, Err_MEMORY);
		return self;
	}
	rep = (NXEPSImageRep *)[[[self toyView] image] bestRepresentation];
	[rep getEPS:&eps length:&n];
	for (i = 0; i < n; i++)
		NXPutc(stream, *eps++);
	NXFlush(stream);
	if (NXSaveToFile(stream, sav))
		errAlert(sav, Err_SAVE);
	NXCloseMemory(stream, NX_FREEBUFFER);
	return self;
}


/* New */
- (NXStream *)rotateEPS: (int)angle name: (const char *)fname error: (int *)err
{
	NXStream *stream;
	NXEPSImageRep *rep;
	NXRect	rect;
	char	*eps;
	int	i, n, dx, dy, lx, ly;

	*err = 0;
	rep = (NXEPSImageRep *)[[[self toyView] image] bestRepresentation];
	[rep getEPS:&eps length:&n];
	[rep getBoundingBox:&rect];
	stream = NXOpenMemory(NULL, 0, NX_READWRITE);
	if (stream == NULL) {
		*err = Err_MEMORY;
		return NULL;
	}
	dx = -(rect.origin.x + rect.size.width);
	dy = -(rect.origin.y + rect.size.height);
	lx = rect.size.width;
	ly = rect.size.height;
	if (angle == 45) {
		dx = (rect.size.height / 2 + 0.5) - rect.origin.x;
		dy = - (rect.size.height / 2 + 0.5) - rect.origin.y;
		lx = (rect.size.height + rect.size.width) * 0.7071 + 0.5;
		ly = lx;
	}else if (angle == 90) {
		dx = -rect.origin.x;
		lx = rect.size.height;
		ly = rect.size.width;
	}else if (angle == 270) {
		dy = -rect.origin.y;
		lx = rect.size.height;
		ly = rect.size.width;
	}else if (angle == Horizontal) {
		dy = -rect.origin.y;
	}else if (angle == Vertical) {
		dx = -rect.origin.x;
	} /* else 180 */

	NXPrintf(stream, "%s\n%s: %s\n",
		"%!PS-Adobe-2.0 EPSF-2.0", "%%Title", fname);
	NXPrintf(stream, "%s: 0 0 %d %d\n%s\n\ngsave\n",
		"%%BoundingBox", lx, ly, "%%EndComments");
	if (angle > 0)
		NXPrintf(stream, "%d rotate\n", angle);
	else
		NXPrintf(stream, "%s scale\n",
			(angle == Horizontal)?"-1 1":"1 -1");
	NXPrintf(stream, "%d %d translate\n%s\n", dx, dy, "%%BeginDocument: ");
	for (i = 0; i < n; i++)
		NXPutc(stream, *eps++);
	NXPrintf(stream, "\n%s\ngrestore\n", "%%EndDocument");
	NXFlush(stream);
	NXSeek(stream, 0L, NX_FROMSTART);
	// NXCloseMemory(stream, NX_FREEBUFFER);
	return stream;
}

/* New */
- (NXStream *)clipEPS: (NXRect *)select error: (int *)err
{
	NXStream *stream;
	NXEPSImageRep *rep;
	NXRect	rect;
	char	*eps, buf[512];
	int	i, n, bp;
	int	loc[4];

	*err = 0;
	rep = (NXEPSImageRep *)[[[self toyView] image] bestRepresentation];
	[rep getEPS:&eps length:&n];
	[rep getBoundingBox:&rect];
	loc[0] = rect.origin.x + select->origin.x;
	loc[1] = rect.origin.y + select->origin.y;
	loc[2] = loc[0] + (int)select->size.width;
	loc[3] = loc[1] + (int)select->size.height;
	stream = NXOpenMemory(NULL, 0, NX_READWRITE);
	if (stream == NULL) {
		*err = Err_MEMORY;
		return NULL;
	}
	for (i = 0, bp = 0; ; i++) {
		if (i >= n) {
			NXCloseMemory(stream, NX_FREEBUFFER);
			*err = Err_ILLG;
			return NULL;
		}
		if ((buf[bp++] = *eps++) >= ' ')
			continue;
		if (strncmp(buf, "%%BoundingBox", 13) == 0) {
			NXPrintf(stream, "%s: %d %d %d %d\n", "%%BoundingBox",
				loc[0], loc[1], loc[2], loc[3]);
			for (++i ; i < n; i++)
				NXPutc(stream, *eps++);
			break;
		}else {
			buf[bp] = 0;
			NXPrintf(stream, "%s", buf);
		}
		bp = 0;
	}
	NXFlush(stream);
	NXSeek(stream, 0L, NX_FROMSTART);
	// NXCloseMemory(stream, NX_FREEBUFFER);
	return stream;
}

@end
